home *** CD-ROM | disk | FTP | other *** search
/ AOL File Library: 2,801 to 2,900 / aol-file-protocol-4400-2801-to-2900.zip / AOLDLs / C++ Files Library / Graphic Gems I, II & III (C_C++) / Graphics Gems C Code.sea / GemsI / Src / AALines / AALines.c < prev    next >
Text File  |  1992-06-16  |  5KB  |  173 lines

  1. /*  FILENAME: AALines.c  [revised 17 AUG 90]
  2.  
  3.     AUTHOR:  Kelvin Thompson
  4.  
  5.     DESCRIPTION:  Code to render an anti-aliased line, from
  6.       "Rendering Anti-Aliased Lines" in _Graphics_Gems_.
  7.  
  8.       This is almost exactly the code printed on pages 690-693
  9.       of _Graphics_Gems_.  An overview of the code is on pages
  10.       105-106.
  11.  
  12.     LINK WITH:
  13.       AALines.h -- Shared tables, symbols, etc.
  14.       AAMain.c -- Calling code for this subroutine.
  15.       AATables.c -- Initialize lookup tables.
  16. */
  17.  
  18.  
  19. #include "AALines.h"
  20.  
  21. #define SWAPVARS(v1,v2) ( temp=v1, v1=v2, v2=temp )
  22.  
  23. #define FIXMUL(f1,f2) \
  24.   ( \
  25.   (((f1&0x0000ffff) * (f2&0x0000ffff)) >> 16) + \
  26.   ((f1&0xffff0000)>>16) * (f2&0x0000ffff) + \
  27.   ((f2&0xffff0000)>>16) * (f1&0x0000ffff) + \
  28.   ((f1&0xffff0000)>>16) * (f2&0xffff0000) \
  29.   )
  30.  
  31. /* HARDWARE ASSUMPTIONS:
  32. /*    * 32-bit, signed ints
  33. /*    * 8-bit pixels, with initialized color table
  34. /*    * pixels are memory mapped in a rectangular fashion */
  35.  
  36. /* FIXED-POINT DATA TYPE */
  37. #ifndef FX_FRACBITS
  38.   typedef int FX;
  39. # define FX_FRACBITS 16  /* bits of fraction in FX format */
  40. # define FX_0        0   /* zero in fixed-point format */
  41. #endif
  42.  
  43. /* ASSUMED MACROS:
  44. /*   SWAPVARS(v1,v2) -- swaps the contents of two variables
  45. /*   PIXADDR(x,y) -- returns address of pixel at (x,y)
  46. /*   COVERAGE(FXdist) -- lookup macro for pixel coverage 
  47.         given perpendicular distance; takes a fixed-point
  48.         integer and returns an integer in the range [0,255]
  49. /*   SQRTFUNC(FXval) -- lookup macro for sqrt(1/(1+FXval^2))
  50.         accepts and returns fixed-point numbers
  51. /*   FIXMUL(FX1,FX2) -- multiplies two fixed-point numbers
  52.         and returns the product as a fixed-point number   */
  53.  
  54. /* BLENDING FUNCTION:
  55. /*  'cover' is coverage -- in the range [0,255]
  56. /*  'back' is background color -- in the range [0,255] */
  57. #define BLEND(cover,back) ((((255-(cover))*(back))>>8)+(cover))
  58.  
  59. /* LINE DIRECTION bits and tables */
  60. #define DIR_STEEP  1  /* set when abs(dy) > abs(dx) */
  61. #define DIR_NEGY   2  /* set whey dy < 0 */
  62.  
  63.  
  64. /* pixel increment values 
  65. /*   -- assume PIXINC(dx,dy) is a macro such that:
  66. /*   PIXADDR(x0,y0) + PIXINC(dx,dy) = PIXADDR(x0+dx,y0+dy)  */
  67. static int adj_pixinc[4] = 
  68.       { PIXINC(1,0), PIXINC(0,1), PIXINC(1,0), PIXINC(0,-1) };
  69. static int diag_pixinc[4] = 
  70.       { PIXINC(1,1), PIXINC(1,1), PIXINC(1,-1), PIXINC(1,-1) };
  71. static int orth_pixinc[4] = 
  72.       { PIXINC(0,1), PIXINC(1,0), PIXINC(0,-1), PIXINC(1,0) };
  73.  
  74. /* Global 'Pmax' is initialized elsewhere.  It is the
  75.    "maximum perpendicular distance" -- the sum of half the
  76.    line width and the effective pixel radius -- in fixed format */
  77. FX Pmax;
  78.  
  79.  
  80. /***************  FUNCTION ANTI_LINE  ***************/
  81.  
  82. void Anti_Line ( X1, Y1, X2, Y2 )
  83. int X1, Y1, X2, Y2;
  84. {
  85. int     Bvar,     /* decision variable for Bresenham's */
  86.         Bainc,   /* adjacent-increment for 'Bvar' */
  87.         Bdinc;   /* diagonal-increment for 'Bvar' */
  88. FX         Pmid,      /* perp distance at Bresenham's pixel */
  89.            Pnow,      /* perp distance at current pixel (ortho loop) */
  90.            Painc,     /* adjacent-increment for 'Pmid' */
  91.            Pdinc,     /* diagonal-increment for 'Pmid' */
  92.            Poinc;     /* orthogonal-increment for 'Pnow'--also equals 'k' */
  93. char     *mid_addr,   /* pixel address for Bresenham's pixel */
  94.          *now_addr;   /* pixel address for current pixel */
  95. int     addr_ainc,   /* adjacent pixel address offset */
  96.         addr_dinc,   /* diagonal pixel address offset */
  97.         addr_oinc;   /* orthogonal pixel address offset */
  98. int dx,dy,dir;        /* direction and deltas */
  99. FX slope;            /* slope of line */
  100. int temp;
  101.  
  102. /* rearrange ordering to force left-to-right */
  103. if     ( X1 > X2 )
  104.       { SWAPVARS(X1,X2);  SWAPVARS(Y1,Y2); }
  105.  
  106. /* init deltas */
  107. dx = X2 - X1;  /* guaranteed non-negative */
  108. dy = Y2 - Y1;
  109.  
  110.  
  111. /* calculate direction (slope category) */
  112. dir = 0;
  113. if ( dy < 0 )   { dir |= DIR_NEGY;  dy = -dy; }
  114. if ( dy > dx )  { dir |= DIR_STEEP; SWAPVARS(dx,dy); }
  115.  
  116. /* init address stuff */
  117. mid_addr = PIXADDR(X1,Y1);
  118. addr_ainc = adj_pixinc[dir];
  119. addr_dinc = diag_pixinc[dir];
  120. addr_oinc = orth_pixinc[dir];
  121.  
  122. /* perpendicular measures */
  123. slope =  (dy << FX_FRACBITS) / dx;
  124. Poinc = SQRTFUNC( slope );
  125. Painc = FIXMUL( slope, Poinc );
  126. Pdinc = Painc - Poinc;
  127. Pmid = FX_0;
  128.  
  129. /* init Bresenham's */
  130. Bainc = dy << 1;
  131. Bdinc = (dy-dx) << 1;
  132. Bvar = Bainc - dx;
  133.  
  134. do
  135.       {
  136.       /* do middle pixel */
  137.       *mid_addr = BLEND( COVERAGE(abs(Pmid)), *mid_addr );
  138.  
  139.       /* go up orthogonally */
  140.       for (
  141.           Pnow = Poinc-Pmid,  now_addr = mid_addr+addr_oinc;
  142.           Pnow < Pmax;
  143.           Pnow += Poinc,      now_addr += addr_oinc
  144.           )
  145.        *now_addr = BLEND( COVERAGE(Pnow), *now_addr );
  146.  
  147.       /* go down orthogonally */
  148.       for (
  149.           Pnow = Poinc+Pmid,  now_addr = mid_addr-addr_oinc;
  150.           Pnow < Pmax;
  151.           Pnow += Poinc,      now_addr -= addr_oinc
  152.           )
  153.        *now_addr = BLEND( COVERAGE(Pnow), *now_addr );
  154.  
  155.  
  156.       /* update Bresenham's */
  157.       if ( Bvar < 0 )
  158.         {
  159.         Bvar += Bainc;
  160.         mid_addr = (char *) ((int)mid_addr + addr_ainc);
  161.         Pmid += Painc;
  162.         }
  163.       else
  164.         {
  165.         Bvar += Bdinc;
  166.         mid_addr = (char *) ((int)mid_addr + addr_dinc);
  167.         Pmid += Pdinc;
  168.         }
  169.  
  170.       --dx;
  171.       } while ( dx >= 0 );
  172. }
  173.